#include "login.h"
#include "ui_login.h"
#include <QMenu>
#include <QMessageBox>
#include "msgbox.h"
#include "shadow.h"
#include <QDebug>
#include "authmanager.h"
#include "frminput2019.h"
#include "userlogger.h"
#include "systempreset.h"

Login::Login(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Login)
{
    ui->setupUi(this);
    bdf = BllDataFlow::getInstance();
    sqlHelper = SqlHelper::getInstance();

    connect(bdf, &BllDataFlow::logoutSignal, this, &Login::userLogoutSlot);
    connect(bdf, &BllDataFlow::changePwDoneSignal, this, &Login::changePwDoneSlot);
    connect(bdf, &BllDataFlow::retranslateUiSignal, this, &Login::retranslateUiSlot);

    setShadow({ui->widget_3,ui->widget_4});
    initWidget();
}

Login::~Login()
{
    delete ui;
}

void Login::showEvent(QShowEvent *)
{
    this->activateWindow();
    ui->pbtnLogin->setFocus();
}

void Login::on_pbtnLogin_clicked()
{
    ui->lineUserName->deselect();
    ui->linePassword->deselect();
    frmInput2019::Instance()->hideAndClearFocus();

    QString userName = ui->lineUserName->text().trimmed();
    QString password = ui->linePassword->text().trimmed();
    rememberPwState = ui->chkRemPw->isChecked();

    User user;
    user.name = userName;

    EttaError ret = sqlHelper->checkLogInfo(userName, password);
    switch (ret) {
    // 以下情况，需要更新登录失败次数
    case EttaError::OK:
    case EttaError::LOGIN_USER_PW_MISMATCH:
    case EttaError::LOGIN_ACCOUNT_LOCKED:
        break;

    // 以下情况，不操作登录失败次数
    case EttaError::LOGIN_NO_USER:
        ui->lineUserName->selectAll();
        MsgBox::information(this,tr("Login Failed"), tr("User does not exist!"));
        return;
    case EttaError::LOGIN_USER_DISABLED:
        MsgBox::information(this, tr("Login Failed"), tr("The current account is not enabled!"));
        return;
    default:
        MsgBox::information(this, tr("Login Failed"), tr("Login error!"));
        return;
    }

    currentUsername = userName;
    currentPassword = password;

    bool loginSuccess = (ret == EttaError::OK);
    int failLoginTimes = setAccountStatus(user, loginSuccess);
    if (loginSuccess)
    {// 登录成功
        bdf->setUserStatusText(currentUsername);
        if (!checkPwValid(password))
        {// 密码强度弱，弹框修改
            UserLogger::log(tr("Password is weak, Require Modify before Login in..."));
            passwordModify->show();
            return;
        }

        UserLogger::log(tr("Login in"));
        bdf->changeMainPageIndex(MainPageIndex::MAIN);
        bdf->setWidgetVisible(sqlHelper->selectUserPermission(user));
        saveParam();
        this->hide();
    }
    else
    {// 登录失败
        QString info = (failLoginTimes >= MAX_WRONG_PW_TIMES) ? tr("Please contact admin to reset password.") : tr("Incorrect password!");
        QString tips = (failLoginTimes >= MAX_WRONG_PW_TIMES) ? tr("The current account is locked") : QString(tr("Remaining input times: %1").arg(MAX_WRONG_PW_TIMES - failLoginTimes));
        UserLogger::log(QString("%1, %2").arg(tr("Login Failed")).arg(tips));

        if (failLoginTimes < MAX_WRONG_PW_TIMES / 2)
        {
            ui->linePassword->selectAll();
            MsgBox::information(this, tr("Login Failed"), tr("Incorrect password!"));
            return;
        }

        MsgBox msgBox;
        msgBox.setTitle(tr("Tips"));
        QString html = QString("<p><span style='color: rgb(255, 0, 0); font-size: 24px;'>%1</span></p>").arg(tips);
        msgBox.setText(html);
        msgBox.setInformativeText(info);
        msgBox.setBtnCancelVisible(false);
        msgBox.exec();
    }
}

void Login::on_lineUserName_returnPressed()
{

}

void Login::on_linePassword_returnPressed()
{

}

void Login::on_btnShowPw_toggled(bool checked)
{
    if (checked)
    {
        QString style = "border:none;border-image:url(:/resources/eye_open.png)";
        ui->btnShowPw->setStyleSheet(style);
        ui->linePassword->setEchoMode(QLineEdit::Normal);
    }
    else
    {
        QString style = "border:none;border-image:url(:/resources/eye_close.png)";
        ui->btnShowPw->setStyleSheet(style);
        ui->linePassword->setEchoMode(QLineEdit::Password);
    }
}

void Login::on_btnForgetPw_clicked()
{
    MsgBox msgbox;
    msgbox.setTitle(QString(tr("Forget Password")));
    msgbox.setText(QString(tr("Please contact our administrator to reset password!")));
    msgbox.setInformativeText(QString(tr("Due to security issues, please contact our administrator to reset password for you if you forget password.")));
    msgbox.setBtnCancelVisible(false);
    msgbox.exec();
}

void Login::retranslateUiSlot()
{
    ui->retranslateUi(this);
}

void Login::userLogoutSlot()
{
    ui->lineUserName->setText(currentUsername);
    ui->linePassword->clear();
}

void Login::changePwDoneSlot()
{
    saveParam();
    if (rememberPwState)
    {
        ui->chkRemPw->setCheckState(Qt::Checked);
        ui->lineUserName->setText(currentUsername);
        ui->linePassword->setText(currentPassword);
    }
    else
    {
        ui->chkRemPw->setCheckState(Qt::Unchecked);
        ui->lineUserName->clear();
        ui->linePassword->clear();
    }
}

void Login::onClearPassword()
{
    ui->linePassword->clear();
    ui->linePassword->setFocus();
}

void Login::readParam()
{
    bool showRememberPw = SystemPreset::instance()->getBoolData(EnumPresetItem::ShowRememberPassWord);
    rememberPwState = SystemPreset::instance()->getBoolData(EnumPresetItem::RememberPassWord);
    currentUsername = SystemPreset::instance()->getStringData(EnumPresetItem::LastLoginUser);

    if (showRememberPw && rememberPwState)
    {
        currentPassword = SystemPreset::instance()->getStringData(EnumPresetItem::LastLoginToken);
        ui->chkRemPw->setCheckState(Qt::Checked);
    }
    else
    {
        ui->chkRemPw->setCheckState(Qt::Unchecked);
    }

    ui->lineUserName->setText(currentUsername);
    ui->linePassword->setText(currentPassword);
    ui->chkRemPw->setVisible(showRememberPw);
}

void Login::saveParam()
{
    rememberPwState = ui->chkRemPw->isChecked();
    SystemPreset::instance()->setData(EnumPresetItem::RememberPassWord, rememberPwState);
    SystemPreset::instance()->setData(EnumPresetItem::LastLoginUser, currentUsername);

    if (rememberPwState)
    {
        SystemPreset::instance()->setData(EnumPresetItem::LastLoginToken, currentPassword);
    }
    else
    {
        SystemPreset::instance()->setData(EnumPresetItem::LastLoginToken, "");
    }
}

void Login::initWidget()
{
    passwordModify = new PasswordModify(this);
    connect(passwordModify, &PasswordModify::done, this, &Login::onClearPassword);

    if (windowWidth >= 1280)
    {
        this->setProperty("cssSize", "large");
    }

    readParam();
    wrongPwInputTimes = 0;

    ui->linePassword->setValidator(gPwValidator);
    ui->lineUserName->setValidator(gUsernameValidator);
}

int Login::setAccountStatus(const User &user, bool loginSuccess)
{
    int failLoginTimes = 0;
    QList<User> userList = sqlHelper->selectUserBasedOnName(user);
    if (userList.count() > 0 && userList[0].status && !AuthManager::instance()->isPresetAccount(userList[0].name))
    {
        failLoginTimes = qMax(0, userList[0].failLoginTimes);
        failLoginTimes = loginSuccess ? 0 : failLoginTimes + 1;
        failLoginTimes = qMin(MAX_WRONG_PW_TIMES, failLoginTimes);
        userList[0].failLoginTimes = failLoginTimes;
        sqlHelper->setFailLoginTimes(userList[0]);
    }

    return failLoginTimes;
}

void Login::on_lineUserName_textChanged(const QString &arg1)
{
    if (arg1.trimmed().length() == 0)
    {
        ui->linePassword->clear();
    }
}
